/*
   Copyright 2009 Bégaudeau Stéphane

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

package faneclipse.ast;

import faneclipse.ast.interfaces.ICompilationUnit;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;

/**
 * @author BEGAUDEAU stephane
 */
public final class FanAbstractSyntaxTreeParser {
	
	/**
	 * Kind constant used to request that the source be parsed as a single expression.
	 */
	public static final int KIND_OF_EXPRESSION = 1;
	
	/**
	 * Kind constant used to request that the source be parsed as a sequence of statements.
	 */
	public static final int KIND_OF_STATEMENTS = 2;
	
	/**
	 * Kind constant used to request that the source be parsed as a sequence of class body declarations.
	 */
	public static final int KIND_OF_CLASS_BODY_DECLARATIONS = 3;
	
	/**
	 * Kind constant used to request that the source be parsed as a compilation unit.
	 */
	public static final int KIND_OF_COMPILATION_UNIT = 4;
	
	/**
	 * Compiler options.
	 */
	private Map<String, String> options;
	
	/**
	 * Indicates if bindings are wanted.
	 */
	private boolean bindings;
	
	/**
	 * the focal position.
	 */
	private int position;
	
	/**
	 * The type of the returned node.
	 */
	private int kind;
	
	/**
	 * The source code to parse.
	 */
	private Object source;
	
	/**
	 * The start position in the source, for our parsing.
	 */
	private int offset;
	
	/**
	 * The length of the area that we will parse, by default -1 (the whole file).
	 */
	private int length;
	
	/**
	 * Indicates if statements should be created.
	 */
	private boolean enabled;
	
	/**
	 * The name of the unit.
	 */
	private String unitName;
	
	/**
	 * The project containing the source.
	 */
	private IProject project;
	
	/**
	 * The constructor.
	 */
	private FanAbstractSyntaxTreeParser() {
		super();
		options = new HashMap<String, String>();
		bindings = false;
		position = Integer.MAX_VALUE;
		kind = FanAbstractSyntaxTreeParser.KIND_OF_COMPILATION_UNIT;
		enabled = false;
		offset = 0;
		length = -1;
	}
	
	/**
	 * Creates a new object for creating a Fan abstract syntax tree.
	 * @return A new FanAbstractSyntaxTreeParser instance.
	 */
	public static FanAbstractSyntaxTreeParser newParser() {
		return new FanAbstractSyntaxTreeParser();
	}
	
	/**
	 * Sets the compiler options to be used when parsing.
	 * @param options The new options.
	 */
	public void setCompilerOptions(final Map<String, String> options) {
		this.options = options;
	}
	
	/**
	 * Set the bindings options (false by default).
	 * @param bindings Indicates if bindings are wanted.
	 */
	public void setResolveBindings(final boolean bindings) {
		this.bindings = bindings;
	}
	
	/**
	 * Set the focal position to create a partial FanAbstractSyntaxTree when a complete on is not needed.
	 * @param position The position in the body declaration.
	 */
	public void setFocalPosition(final int position) {
		this.position = position;
	}
	
	/**
	 * Sets the kind of constructs to be parsed from the source. Defaults to an entire compilation unit.
	 * @param kind The kind of construct to parse: one of KIND_OF_COMPILATION_UNIT, KIND_OF_CLASS_BODY_DECLARATIONS, KIND_OF_EXPRESSION, KIND_OF_STATEMENTS
	 */
	public void setKind(final int kind) {
		switch(kind) {
		case 1: this.kind = kind;
			break;
		case 2: this.kind = kind;
			break;
		case 3: this.kind = kind;
			break;
		case 4: this.kind = kind;
			break;
		default: this.kind = FanAbstractSyntaxTreeParser.KIND_OF_COMPILATION_UNIT;
			break;
		}
	}
	
	/**
	 * Set the source code to parse.
	 * @param source The source code.
	 */
	public void setSource(final String source) {
		this.source = source;
	}
	
	/**
	 * Sets the source code to be parsed.
	 * @param source The compilation unit that we will parse.
	 */
	public void setSource(final ICompilationUnit source) {
		this.source = source;
	}
	
	/**
	 * @param offset The index of the first character to parse.
	 * @param length The number of characters to parse.
	 */
	public void setSourceRange(final int offset, final int length) {
		this.offset = offset;
		this.length = length;
	}
	
	/**
	 * Set the statements options (default false).
	 * @param enabled Indicates if statements are wanted.
	 */
	public void setStatementsRecovery(final boolean enabled) {
		this.enabled = enabled;
	}
	
	/**
	 * Sets the name of the compilation unit that would hypothetically contains the source string.
	 * If setSource(Foo) and setProject(Bar) and the source in the package test then setUnitName(/Bar/test/Foo.java).
	 * @param unitName The name of the compilation unit that would containt the source.
	 */
	public void setUnitName(final String unitName) {
		this.unitName = unitName;
	}
	
	/**
	 * Set the project containing the source.
	 * @param project The project containing the source.
	 */
	public void setProject(final IProject project) {
		this.project = project;
	}
	
	/**
	 * Creates an Fan abstract syntax tree.
	 * @param monitor The progress monitor used to report progress and request cancelation, or null if none
	 * @return An FanAbstractSyntaxTree node whose type depends on the kind of parse requested
	 * @throws IllegalStateException If the setting are invalids.
	 */
	public FanAbstractSyntaxTreeNode createFanAbstractSyntaxTree(final IProgressMonitor monitor) throws IllegalStateException {
		if(1>2)
		{
			throw new IllegalStateException("Invalid parameters");
		}
		
		return null;
	}
}
